#include "List.h"

List::List() {
	this->root = NULL;
	this->current = this->root;
	this->cantElementos=0;
}

List::~List() {
	while(!this->isEmpty()){
		this->removeElement();
	}
	delete current;
	delete root;
}

void List::appendElement(TermYFrecQuery* element){
	assert(element!=NULL);

	if (isEmpty()){
		this->root = new NodeList();
		this->current = this->root;
	}else{
		while(this->moveNext());
		NodeList* newNode = new NodeList();
		newNode->setPrevNode(this->current);
		this->current->setNextNode(newNode);
		this->current = this->current->getNextNode();
	}
	this->setElement(element);
	cantElementos++;
}

void List::removeElement(){
	this->current->dispose();
	this->dispose();
}

void List::setElement(TermYFrecQuery* element){
	assert(element!=NULL);
	this->current->setElement(element);
}

TermYFrecQuery* List::getElement(){
	return this->current->getElement();
}

TermYFrecQuery* List::getElement(int i){
	this->moveRoot();
	int j = 0;
	while (j < i){
		this->moveNext();
		j++;
	}
	return this->current->getElement();
}

int List::getSize(){
	return cantElementos;
}

bool List::isEmpty(){
	return (this->getSize() == 0);
}

void List::moveRoot(){
	this->current = this->root;
}

bool List::movePrev(){
	if (this->current->getPrevNode() != NULL){
		this->current = this->current->getPrevNode();
		return true;
	}else
		return false;
}

bool List::moveNext(){
	if (this->current->getNextNode() != NULL){
		this->current = this->current->getNextNode();
		return true;
	}else
		return false;
}

void List::dispose(unsigned int pos) {
	this->moveRoot();
	unsigned int j = 0;
	while (j < pos){
		this->moveNext();
		j++;
	}

	dispose();
}

void List::dispose(){
	NodeList* nextNodeList = current->getNextNode();
	NodeList* prevNodeList = current->getPrevNode();
	if (prevNodeList != NULL)
		prevNodeList->setNextNode(nextNodeList);
	if(nextNodeList != NULL)
		nextNodeList->setPrevNode(prevNodeList);
	delete(current);
	this->current = prevNodeList;
	if (current == NULL) {
		current = nextNodeList;
		root = current;
	}
	cantElementos--;
}

TermYFrecQuery* List::buscar(string token) {

	bool encontrado = false;
	bool eol = false;
	TermYFrecQuery* datos;

	if (this->isEmpty())
		eol = true;
	this->moveRoot();

	string tokenSearched = string("");
	while (!eol && !encontrado) {
		tokenSearched = this->getElement()->termino;
		if(strcmp(token.c_str(), tokenSearched.c_str()) == 0) {
			datos = this->getElement();
			encontrado = true;
		}
		eol = !(this->moveNext());
	}
	if(encontrado == true)
		return datos;
	else
		return NULL;
}

void List::insertar(TermYFrecQuery* nodo) {

	bool encontrado = false;
	bool eol = false;
	bool insertado = false;
	string token = nodo->termino;

	if(isEmpty()) {
		this->root = new NodeList(nodo);
		this->current = this->root;
		cantElementos++;
	} else {
		this->moveRoot();
		string tokenSearched = string("");

		while (!eol && !encontrado && !insertado) {
			tokenSearched = this->getElement()->termino;
			int strCmp = strcmp(token.c_str(), tokenSearched.c_str());

			if( strCmp > 0) {
				//TODO logica para insertar
				//o sea el puntero del anterior tiene que apuntar al nuevo
				//y el puntero al siguiente del nuevo apuntar al otro
				NodeList* nuevoNodo = new NodeList();

				NodeList* siguiente = this->current;

				nuevoNodo->setNextNode(siguiente);

				if(this->movePrev()) {
					nuevoNodo->setPrevNode(this->current);
					this->current->setNextNode(nuevoNodo);
				} else {
					//tengo que cambiar el root
					this->root = nuevoNodo;
					nuevoNodo->setPrevNode(NULL);
				}
				siguiente->setPrevNode(nuevoNodo);

				nuevoNodo->setElement(nodo);
				cantElementos++;
				insertado = true;
				current = nuevoNodo;
			} else if ( strCmp == 0) {
				encontrado = true;
				this->getElement()->vecesFueConsultado++;
				insertado = true;
			}
			eol = !(this->moveNext());
		}

		if(!insertado)
			this->appendElement(nodo);
	}
}

void List::insertar(string token, vector<Data>* datos) {
	TermYFrecQuery* term = new TermYFrecQuery();
	term->termino = token;
	term->vecesFueConsultado = 1;
	term->datosTermino = datos;
	insertar(term);
}
